/******************************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Ltd.                       */
/*                                                                            */
/*  NAME      = db2_response.c                                                */
/*  NOTE      = TDS 请求解析                                                  */
/*  DATE      = 2015/03/19 by zhengxd                                         */
/******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

#include "db2_core.h"
#include "db2_froca.h"
#include "db2_exter.h"
#include "db2_param.h"
#include "db2_obj.h"
#include "db2_reply_msg.h"
#include "db2_error_msg.h"
#include "db2_response.h"

extern void *g_p_apm_context;

/*******************************************************************************
*  FUNC     :  response时上报request
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(保存Frreport_data)
*           :  p_st_cmd(request信息)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_report_resp_req(Conntrack *p_st_conn
                                 , Frhash_header *p_st_hash_report
                                 , Db2_req_cmd *p_st_cmd
                                 , L7session_db2 *p_st_sess)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    Frreport_body_data *p_st_report_body = NULL;

    p_st_cmd->i_close_flg = DB2_TRUE;

    /* 创建report body */
    p_st_report_body = db2_new_report_body(p_st_conn, p_st_sess);
    /* 创建report body失败时，不释放做成的request */
    if (p_st_report_body == NULL)
    {
        frdbg("sqlserver_new_report_body failed!\n");
        return APM_L7_ANALYZE_SUCC;
    }
    /* 上报request数据 */
    i_ret = frdb_report_req2(p_st_conn, p_st_hash_report
                             , p_st_cmd->p_st_statement
                             , p_st_cmd->p_st_resultset
                             , &p_st_report_body);
    /* 上报request数据失败时，不释放做成的request */
    if (i_ret != FR_SUCC)
    {
        frdbg("frdb_report_req2 failed!\n");
        frreport_body_free(&p_st_report_body);
        return APM_L7_ANALYZE_SUCC;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  response时上报reponse
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(保存Frreport_data)
*           :  p_st_cmd(request信息)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_report_resp(Conntrack *p_st_conn
                             , Frhash_header *p_st_hash_report
                             , L7session_db2_private *p_st_private)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    long l_report_pre = -1;
    Db2_req_cmd *p_st_cmd = NULL;
    Frlist_node *p_st_node = NULL;
    Frreport_body_data *p_st_report_body = NULL;

    /* 根据command list逐一上报 */
    p_st_node = FRLIST_FIRST_NODE(&(p_st_private->p_st_req->st_command_lst));
    while (p_st_node)
    {
        p_st_cmd = (Db2_req_cmd *)FRLIST_GET_NODE_DATA(p_st_node);
        switch (p_st_cmd->i_req_cmd_cp)
        {
            case DRDA_CP_CLSQRY:
            case DRDA_CP_EXCSQLSTT:
                /* 上一次已经上报过了 */
                if (l_report_pre == p_st_cmd->l_cursor_id)
                {
                    break;
                }
                l_report_pre = p_st_cmd->l_cursor_id;

            case DRDA_CP_EXCSQLSET:
            case DRDA_CP_RDBCMM:
            case DRDA_CP_EXCSQLIMM:
            case DRDA_CP_RDBRLLBCK:
            case DRDA_CP_SYNCCTL:
                /* 创建report body */
                p_st_report_body = db2_new_report_body(p_st_conn, p_st_private->p_st_sess);
                /* 创建report body失败时，不释放做成的request */
                if (p_st_report_body == NULL)
                {
                    frdbg("db2_new_report_body failed!\n");
                    if (p_st_cmd->i_req_cmd_cp == DRDA_CP_CLSQRY)
                    {
                        frdb_del_first_resultset(p_st_cmd->p_st_statement);
                    }
                    return APM_L7_ANALYZE_FAIL;
                }

                /* 上报response数据 */
                i_ret = frdb_report_resp2(p_st_conn, p_st_hash_report
                                         , p_st_cmd->p_st_statement
                                         , p_st_cmd->p_st_resultset
                                         , p_st_cmd->i_error_code
                                         , p_st_cmd->p_error_msg
                                         , p_st_cmd->p_error_msg
                                         , &p_st_report_body);
                if (i_ret != FR_SUCC)
                {
                    frdbg("frdb_report_resp2 failed!\n");
                    frreport_body_free(&p_st_report_body);
                    if (p_st_cmd->i_req_cmd_cp == DRDA_CP_CLSQRY)
                    {
                        frdb_del_first_resultset(p_st_cmd->p_st_statement);
                    }
                    return APM_L7_ANALYZE_FAIL;
                }

                /* CLSQRY */
                if (p_st_cmd->i_req_cmd_cp == DRDA_CP_CLSQRY)
                {
                    l_report_pre = -1;
                    frdb_del_first_resultset(p_st_cmd->p_st_statement);
                    /* 清空metadata*/
                    frlist_remove_all(&p_st_cmd->p_st_statement->st_metadata_column
                                     , frdb_metadata_node_free);
                }
                else
                {
                    frdb_init_resultset(p_st_cmd->p_st_resultset
                                       , frct_seq_increase(p_st_conn));
                }
                break;

            default:
                if (p_st_cmd->i_close_flg == DB2_TRUE
                   || (p_st_cmd->p_st_resultset && p_st_cmd->i_error_code < 0))
                {
                    /* 上一次已经上报过了 */
                    if (l_report_pre == p_st_cmd->l_cursor_id)
                    {
                        break;
                    }
                    l_report_pre = p_st_cmd->l_cursor_id;

                    /* 创建report body */
                    p_st_report_body = db2_new_report_body(p_st_conn, p_st_private->p_st_sess);
                    /* 创建report body失败时，不释放做成的request */
                    if (p_st_report_body == NULL)
                    {
                        frdbg("db2_new_report_body failed!\n");
                        return APM_L7_ANALYZE_FAIL;
                    }

                    /* 上报response数据 */
                    i_ret = frdb_report_resp2(p_st_conn, p_st_hash_report
                                             , p_st_cmd->p_st_statement
                                             , p_st_cmd->p_st_resultset
                                             , p_st_cmd->i_error_code
                                             , p_st_cmd->p_error_msg
                                             , p_st_cmd->p_error_msg
                                             , &p_st_report_body);
                    if (i_ret != FR_SUCC)
                    {
                        frdbg("frdb_report_resp2 failed!\n");
                        frreport_body_free(&p_st_report_body);
                        return APM_L7_ANALYZE_FAIL;
                    }
                    /* 初始化resultset */
                    frdb_init_resultset(p_st_cmd->p_st_resultset
                                       , frct_seq_increase(p_st_conn));
                    /* 清空metadata*/
                    frlist_remove_all(&p_st_cmd->p_st_statement->st_metadata_column
                                     , frdb_metadata_node_free);
                }
                break;
        }

        /* 取得节点 */
        p_st_node = FRLIST_NEXT_NODE(p_st_node);
    }

    return APM_L7_ANALYZE_SET_RESP(APM_L7_ANALYZE_SUCC);
}

/*******************************************************************************
*  FUNC     :  DDM request后处理
*  ARGS     :  p_st_resp (response command信息)
*           :  p_st_cmd_cp(对应command信息)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_end_resp_cmd(L7session_db2_private *p_st_private
                             , Db2_req_cmd *p_st_cmd_cp)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    L7_resp_db2 *p_st_resp = p_st_private->p_st_resp;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Sql_resultset *p_st_resultset = p_st_cmd_cp->p_st_resultset;

    switch (p_st_cmd_cp->i_req_cmd_cp)
    {
        /* 设置sql语句影响行数 */
        case DRDA_CP_EXCSQLSTT:
        case DRDA_CP_EXCSQLIMM:
        case DRDA_CP_RDBCMM:
        case DRDA_CP_RDBRLLBCK:
        case DRDA_CP_SYNCCTL:
            i_ret = frdb_set_resultset_resp2(p_st_resultset
                                            , p_st_resp->ui_ddm_len
                                            , 1
                                            , &p_st_resp->ul_effect_rows
                                            , &(p_st_fragment->st_start_timestamp)
                                            , &(p_st_fragment->st_timestamp));
            break;

        /* 设置select语句fetch行数 */
        case DRDA_CP_OPNQRY:
        case DRDA_CP_CNTQRY:
        case DRDA_CP_CLSQRY:
            i_ret = frdb_set_resultset_resp2(p_st_resultset
                                            , p_st_resp->ui_ddm_len
                                            , 1
                                            , &p_st_resp->ul_rows
                                            , &(p_st_fragment->st_start_timestamp)
                                            , &(p_st_fragment->st_timestamp));
            break;

        default:
            /* 纯粹这是长度 */
            i_ret = frdb_set_resultset_resp2(p_st_resultset
                                            , p_st_resp->ui_ddm_len
                                            , 0
                                            , NULL
                                            , &(p_st_fragment->st_start_timestamp)
                                            , &(p_st_fragment->st_timestamp));
            break;
    }

    if (i_ret != FR_SUCC)
    {
        frdbg("frdb_set_resultset_resp2 failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    /* 如果有错误信息,设置 */
    if (p_st_resp->i_error_code < 0)
    {
        p_st_cmd_cp->i_error_code = p_st_resp->i_error_code;
        p_st_cmd_cp->p_error_msg = p_st_resp->p_error_msg;
        p_st_resp->p_error_msg = NULL;
    }
    /* 追加到hash */
    else if (p_st_cmd_cp->i_req_cmd_cp == DRDA_CP_PRPSQLSTT)
    {
        i_ret = frdb_add_statement(p_st_private->p_hash_prepare
                                   , p_st_cmd_cp->l_cursor_id
                                   , p_st_cmd_cp->p_st_statement);
        if (i_ret != FR_SUCC)
        {
            frdbg("frdb_add_statement failed!\n");
            return APM_L7_ANALYZE_FAIL;
        }
        p_st_cmd_cp->i_new_flg = DB2_FALSE;
    }

    /* 初始化response 信息 */
    p_st_resp->i_error_code = 0;
    p_st_resp->ui_ddm_len = 0;
    p_st_resp->ul_rows = 0;
    if (p_st_resp->p_error_msg)
    {
        frfree(p_st_resp->p_error_msg);
        p_st_resp->p_error_msg = NULL;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析EXCSAT对应的响应
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(保存Frreport_data)
*           :  p_st_private(DB2是有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_parse_excsat_resp(Conntrack *p_st_conn
                                  , Frhash_header *p_st_hash_report
                                  , L7session_db2_private *p_st_private
                                  , int i_whole_flg
                                  , Db2_req_cmd *p_st_cmd_cp)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_ddm_cp = 0;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    while (bytebuff_remaining(p_st_data) > 0)
    {
        /* 取得当前DDM的code point */
        i_ret = db2_get_ddm_cp(p_st_fragment, i_whole_flg, &i_ddm_cp
                              , &p_st_private->p_st_resp->ui_ddm_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("EXCSAT response: need more data or parse failed!\n");
            return i_ret;
        }

        switch (i_ddm_cp)
        {
            case DRDA_CP_EXCSATRD: //Normal reply data object
                i_ret = db2_parse_excsatrd(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_RDBNFNRM: //RDB Not Found
                i_ret = db2_parse_rdbnfnrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_AGNPRMRM: //Permanent Agent Error
                i_ret = db2_parse_agnprmrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDATHRM: //Not Authorized to Command
                i_ret = db2_parse_cmdathrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDCHKRM: //Command Check
                i_ret = db2_parse_cmdchkrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDNSPRM: //Command Not Supported
                i_ret = db2_parse_cmdnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_MGRDEPRM: //Manager Dependency Error
                i_ret = db2_parse_mgrdeprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_MGRLVLRM: //Manager-level Conflict MINLVL 2
                i_ret = db2_parse_mgrlvlrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PRCCNVRM: //Conversational Protocol Error
                i_ret = db2_parse_prccnvrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PRMNSPRM: //Parameter Not Supported
                i_ret = db2_parse_prmnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_RSCLMTRM: //Resource Limits Reached
                i_ret = db2_parse_rsclmtrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_SYNTAXRM: //Data Stream Syntax Error
                i_ret = db2_parse_syntaxrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_TRGNSPRM: //Target Not Supported
                i_ret = db2_parse_trgnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_VALNSPRM: //Parameter Value Not Supported
                i_ret = db2_parse_valnsprm(p_st_private, i_whole_flg);
                break;

            default:
                frdbg("EXCSAT: Unknow parameter!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 需要更多的数据或者解析出错 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("EXCSAT: need more data or parse failed!\n");
            return i_ret;
        }

        /* 设置position */
        p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
        /* 当前object或者message解析完成 */
        p_st_fragment->i_req_resp_cp = DRDA_CP_NULL;
        /* 下一个可能存在的DDM object属于下一个command的response */
        if (p_st_fragment->i_correlator_flg == DB2_FALSE)
        {
            break;
        }
    }

    /* 当前数据解析完了之后还有后续DDM属于当前response */
    if (p_st_fragment->i_correlator_flg == DB2_TRUE)
    {
        frdbg("EXCSAT: need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析ACCSEC对应的响应
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(保存Frreport_data)
*           :  p_st_private(DB2是有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_parse_accsec_resp(Conntrack *p_st_conn
                                  , Frhash_header *p_st_hash_report
                                  , L7session_db2_private *p_st_private
                                  , int i_whole_flg
                                  , Db2_req_cmd *p_st_cmd_cp)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_ddm_cp = 0;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    while (bytebuff_remaining(p_st_data) > 0)
    {
        /* 取得当前DDM的code point */
        i_ret = db2_get_ddm_cp(p_st_fragment, i_whole_flg, &i_ddm_cp
                              , &p_st_private->p_st_resp->ui_ddm_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("ACCSEC response: need more data or parse failed!\n");
            return i_ret;
        }

        switch(i_ddm_cp)
        {
            case DRDA_CP_ACCSECRD: //Normal reply data object
                i_ret = db2_parse_accsecrd(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_KERSECPPL: //Kerberos Security Principal
                i_ret = db2_skip_ddm(p_st_fragment, i_whole_flg);
                break;

            case DRDA_CP_RDBNFNRM: //RDB Not Found
                i_ret = db2_parse_rdbnfnrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_AGNPRMRM: // Permanent Agent Error
                i_ret = db2_parse_agnprmrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDATHRM: // Not Authorized to Command
                i_ret = db2_parse_cmdathrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDCHKRM: // Command Check
                i_ret = db2_parse_cmdchkrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDNSPRM: // Command Not Supported
                i_ret = db2_parse_cmdnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PRCCNVRM: // Conversational Protocol Error
                i_ret = db2_parse_prccnvrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PRMNSPRM: // Parameter Not Supported
                i_ret = db2_parse_prmnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_RDBAFLRM: // RDB Access Failed Reply Message
                i_ret = db2_parse_rdbaflrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_RSCLMTRM: // Resource Limits Reached
                i_ret = db2_parse_rsclmtrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_SYNTAXRM: // Data Stream Syntax Error
                i_ret = db2_parse_syntaxrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_TRGNSPRM: // Target Not Supported
                i_ret = db2_parse_trgnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_VALNSPRM: // Parameter Value Not Supported
                i_ret = db2_parse_valnsprm(p_st_private, i_whole_flg);
                break;

            default:
                frdbg("ACCSEC: Unknow parameter!\n");
                return APM_L7_ANALYZE_FAIL;

        }

        /* 需要更多的数据或者解析出错 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("ACCSEC: need more data or parse failed!\n");
            return i_ret;
        }

        /* 设置position */
        p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
        /* 当前object或者message解析完成 */
        p_st_fragment->i_req_resp_cp = DRDA_CP_NULL;
        /* 下一个可能存在的DDM object属于下一个command的response */
        if (p_st_fragment->i_correlator_flg == DB2_FALSE)
        {
            break;
        }
    }

    /* 当前数据解析完了之后还有后续DDM属于当前response */
    if (p_st_fragment->i_correlator_flg == DB2_TRUE)
    {
        frdbg("ACCSEC: need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析SECCHK对应的响应
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(保存Frreport_data)
*           :  p_st_private(DB2是有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_parse_secchk_resp(Conntrack *p_st_conn
                                  , Frhash_header *p_st_hash_report
                                  , L7session_db2_private *p_st_private
                                  , int i_whole_flg
                                  , Db2_req_cmd *p_st_cmd_cp)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_ddm_cp = 0;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    while (bytebuff_remaining(p_st_data) > 0)
    {
        /* 取得当前DDM的code point */
        i_ret = db2_get_ddm_cp(p_st_fragment, i_whole_flg, &i_ddm_cp
                              , &p_st_private->p_st_resp->ui_ddm_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("SECCHK response: need more data or parse failed!\n");
            return i_ret;
        }

        switch(i_ddm_cp)
        {
            /* 跳过该object */
            case DRDA_CP_SECTKN:
                i_ret = db2_skip_ddm(p_st_fragment, i_whole_flg);
                break;

            case DRDA_CP_SECCHKRM:
                i_ret = db2_parse_secchkrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_AGNPRMRM:  //Permanent Agent Error
                i_ret = db2_parse_agnprmrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDATHRM:  //Not Authorized to Command
                i_ret = db2_parse_cmdathrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDCHKRM:  //Command Check
                i_ret = db2_parse_cmdchkrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDNSPRM:  //Command Not Supported
                i_ret = db2_parse_cmdnsprm(p_st_private, i_whole_flg);
                break;

//            case DRDA_CP_INVRQSRM:  //Invalid Request to do 协议未定义
//                i_ret = db2_parse_invrqsrm(p_st_private, i_whole_flg);
//                break;

            case DRDA_CP_MGRDEPRM:  //Manager Dependency Error
                i_ret = db2_parse_mgrdeprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_OBJNSPRM:  //Object Not Supported
                i_ret = db2_parse_objnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PRCCNVRM:  //Conversational Protocol Error
                i_ret = db2_parse_prccnvrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PRMNSPRM:  //Parameter Not Supported
                i_ret = db2_parse_prmnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_RDBAFLRM:  //RDB Access Failed Reply Message
                i_ret = db2_parse_rdbaflrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_RSCLMTRM:  //Resource Limits Reached
                i_ret = db2_parse_rsclmtrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_SYNTAXRM:  //Data Stream Syntax Error
                i_ret = db2_parse_syntaxrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_TRGNSPRM:  //Target Not Supported
                i_ret = db2_parse_trgnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_VALNSPRM:  //Parameter Value Not Supported
                i_ret = db2_parse_valnsprm(p_st_private, i_whole_flg);
                break;

            default:
                frdbg("SECCHK: Unknow DDM!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 需要更多的数据或者解析出错 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("SECCHK: need more data or parse failed!\n");
            return i_ret;
        }

        /* 设置position */
        p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
        /* 当前object或者message解析完成 */
        p_st_fragment->i_req_resp_cp = DRDA_CP_NULL;
        /* 下一个可能存在的DDM object属于下一个command的response */
        if (p_st_fragment->i_correlator_flg == DB2_FALSE)
        {
            break;
        }
    }

    /* 当前数据解析完了之后还有后续DDM属于当前response */
    if (p_st_fragment->i_correlator_flg == DB2_TRUE)
    {
        frdbg("SECCHK: need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析ACCRDB对应的响应
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(保存Frreport_data)
*           :  p_st_private(DB2是有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_parse_accrdb_resp(Conntrack *p_st_conn
                                  , Frhash_header *p_st_hash_report
                                  , L7session_db2_private *p_st_private
                                  , int i_whole_flg
                                  , Db2_req_cmd *p_st_cmd_cp)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_ddm_cp = 0;
    L7_resp_db2 *p_st_resp = p_st_private->p_st_resp;
    L7session_db2 *p_st_sess = p_st_private->p_st_sess;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;
    Frreport_data *p_st_report_data=NULL;
    char arr_info[128] = {0};

    while (bytebuff_remaining(p_st_data) > 0)
    {
        /* 取得当前DDM的code point */
        i_ret = db2_get_ddm_cp(p_st_fragment, i_whole_flg, &i_ddm_cp
                              , &p_st_private->p_st_resp->ui_ddm_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("ACCRDB response: need more data or parse failed!\n");
            return i_ret;
        }

        switch(i_ddm_cp)
        {
            case DRDA_CP_TYPDEFNAM: //data type definition name
            case DRDA_CP_TYPDEFOVR: //data type definition override
                i_ret = db2_skip_ddm(p_st_fragment, i_whole_flg);
                break;

            /* 解析 */
            case DRDA_CP_SQLCARD:
                i_ret = db2_parse_sqlcard(p_st_private, i_whole_flg
                                         , &p_st_resp->i_error_code
                                         , p_st_resp->arr_sqlstate, NULL);
                break;

            case DRDA_CP_ACCRDBRM:
                i_ret = db2_parse_accrdbrm(p_st_private, i_whole_flg);

            case DRDA_CP_AGNPRMRM:  //Permanent Agent Error
                i_ret = db2_parse_agnprmrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDATHRM:  //Not Authorized to Command
                i_ret = db2_parse_cmdchkrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDCHKRM:  //Command Check
                i_ret = db2_parse_cmdchkrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDNSPRM:  //Command Not Supported
                i_ret = db2_parse_cmdnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_MGRDEPRM:  //Manager Dependency Error
                i_ret = db2_parse_mgrdeprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PRCCNVRM:  //Conversational Protocol Error
                i_ret = db2_parse_prccnvrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PRMNSPRM:  //Parameter Not Supported
                i_ret = db2_parse_prmnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_RDBACCRM:  //RDB Currently Accessed
                i_ret = db2_parse_rdbaccrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_RDBAFLRM:  //RDB Access Failed Reply Message
                i_ret = db2_parse_rdbaflrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_RDBATHRM:  //Not Authorized to RDB
                i_ret = db2_parse_rdbathrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_RDBNFNRM:  //RDB Not Found
                i_ret = db2_parse_rdbnfnrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_RSCLMTRM:  //Resource Limits Reached
                i_ret = db2_parse_rsclmtrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_SYNTAXRM:  //Data Stream Syntax Error
                i_ret = db2_parse_syntaxrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_TRGNSPRM:  //Target Not Supported
                i_ret = db2_parse_trgnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_VALNSPRM:  //Parameter Value Not Supported
                i_ret = db2_parse_valnsprm(p_st_private, i_whole_flg);
                break;

            default:
                frdbg("ACCRDB: Unknow DDM!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 需要更多的数据或者解析出错 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("ACCRDB: need more data or parse failed!\n");
            return i_ret;
        }

        /* 设置position */
        p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
        /* 当前object或者message解析完成 */
        p_st_fragment->i_req_resp_cp = DRDA_CP_NULL;
        /* 下一个可能存在的DDM object属于下一个command的response */
        if (p_st_fragment->i_correlator_flg == DB2_FALSE)
        {
            break;
        }
    }

    /* 当前数据解析完了之后还有后续DDM属于当前response */
    if (p_st_fragment->i_correlator_flg == DB2_TRUE)
    {
        frdbg("ACCRDB: need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }

    if (p_st_sess->p_db_user)
    {
        snprintf(arr_info, sizeof(arr_info), "%s login", p_st_sess->p_db_user);
    }
    else
    {
        snprintf(arr_info, sizeof(arr_info), "login");
    }
    /* 设置login成功时间 */
    if (p_st_private->p_st_resp->i_error_code >= 0)
    {
        p_st_sess->st_login = p_st_fragment->st_timestamp;
        p_st_report_data = frreport_update_create(p_st_conn, APM_REPORT_UPDATE_LOGON, arr_info, &p_st_fragment->st_timestamp);
    }
    else
    {
        p_st_report_data = frreport_update_create(p_st_conn, APM_REPORT_UPDATE_LOGON_REJECT, arr_info, &p_st_fragment->st_timestamp);
    }
    if (p_st_report_data)
    {
        i_ret = frreport_send(g_p_apm_context, &p_st_report_data);
        if (i_ret != FR_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析EXCSQLSET对应的响应
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(保存Frreport_data)
*           :  p_st_private(DB2是有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_parse_excsqlset_resp(Conntrack *p_st_conn
                                     , Frhash_header *p_st_hash_report
                                     , L7session_db2_private *p_st_private
                                     , int i_whole_flg
                                     , Db2_req_cmd *p_st_cmd_cp)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_ddm_cp = 0;
    L7_resp_db2 *p_st_resp = p_st_private->p_st_resp;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    while (bytebuff_remaining(p_st_data) > 0)
    {
        /* 取得当前DDM的code point */
        i_ret = db2_get_ddm_cp(p_st_fragment, i_whole_flg, &i_ddm_cp
                              , &p_st_resp->ui_ddm_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("EXCSQLSET response: need more data or parse failed!\n");
            return i_ret;
        }

        switch(i_ddm_cp)
        {
            /* 跳过该object */
            case DRDA_CP_MGRLVLOVR:  //manager level overrides
            case DRDA_CP_MONITORRD:  //monitor reply data
            case DRDA_CP_TYPDEFNAM:  //data type definition name
            case DRDA_CP_TYPDEFOVR:  //data type definition override
                i_ret = db2_skip_ddm(p_st_fragment, i_whole_flg);
                break;

            case DRDA_CP_SQLCARD:    //SQLCA reply data
                i_ret = db2_parse_sqlcard(p_st_private, i_whole_flg
                                         , &p_st_resp->i_error_code
                                         , p_st_resp->arr_sqlstate, NULL);
                break;

            case DRDA_CP_ABNUOWRM:  //Abnormal End Unit of Work Condition
                i_ret = db2_parse_abnuowrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_AGNPRMRM:  //Permanent Agent Error
                i_ret = db2_parse_agnprmrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDATHRM:  //Not Authorized to Command
                i_ret = db2_parse_cmdathrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDCHKRM:  //Command Check
                i_ret = db2_parse_cmdchkrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDNSPRM:  //Command Not Supported
                i_ret = db2_parse_cmdnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_DSCINVRM:  //Invalid Descriptor
                i_ret = db2_parse_dscinvrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_DTAMCHRM:  //Data Descriptor Mismatch
                i_ret = db2_parse_dtamchrm(p_st_private, i_whole_flg);
                break;

            /* 根据DB2协议EXCSQLSET没有正常的reply message */
            //case DRDA_CP_ENDUOWRM:  //End Unit of Work Condition
            //    i_ret = db2_parse_enduowrm(p_st_private, i_whole_flg);
            //    break;

            case DRDA_CP_OBJNSPRM:  //Object Not Supported
                i_ret = db2_parse_objnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PRCCNVRM:  //Conversational Protocol Error
                i_ret = db2_parse_prccnvrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PRMNSPRM:  //Parameter Not Supported
                i_ret = db2_parse_prmnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_RDBNACRM:  //RDB Not Accessed
                i_ret = db2_parse_rdbnacrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_RSCLMTRM:  //Resource Limit Reached
                i_ret = db2_parse_syntaxrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_SQLERRRM:  //SQL Error Condition
                i_ret = db2_parse_syntaxrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_SYNTAXRM:  //Data Stream Syntax Error
                i_ret = db2_parse_syntaxrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_TRGNSPRM:  //Target Not Supported
                i_ret = db2_parse_trgnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_VALNSPRM:  //Parameter Value Not Supported
                i_ret = db2_parse_valnsprm(p_st_private, i_whole_flg);
                break;

            default:
                frdbg("EXCSQLSET response: Unknow DDM!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 需要更多的数据或者解析出错 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("EXCSQLSET response: need more data or parse failed!\n");
            return i_ret;
        }

        /* 设置position */
        p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
        /* 当前object或者message解析完成 */
        p_st_fragment->i_req_resp_cp = DRDA_CP_NULL;
        /* 下一个可能存在的DDM object属于下一个command的response */
        if (p_st_fragment->i_correlator_flg == DB2_FALSE)
        {
            i_ret = __db2_end_resp_cmd(p_st_private, p_st_cmd_cp);
            return i_ret;
        }
    }

    return APM_L7_ANALYZE_TODO;
}

/*******************************************************************************
*  FUNC     :  解析PRPSQLSTT对应的响应
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(保存Frreport_data)
*           :  p_st_private(DB2是有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_parse_prpsqlstt_resp(Conntrack *p_st_conn
                                     , Frhash_header *p_st_hash_report
                                     , L7session_db2_private *p_st_private
                                     , int i_whole_flg
                                     , Db2_req_cmd *p_st_cmd_cp)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_ddm_cp = 0;
    L7_resp_db2 *p_st_resp = p_st_private->p_st_resp;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    while (bytebuff_remaining(p_st_data) > 0)
    {
        /* 取得当前DDM的code point */
        i_ret = db2_get_ddm_cp(p_st_fragment, i_whole_flg, &i_ddm_cp
                              , &p_st_private->p_st_resp->ui_ddm_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("PRPSQLSTT response: need more data or parse failed!\n");
            return i_ret;
        }

        switch(i_ddm_cp)
        {
            /* 跳过该object */
            case DRDA_CP_TYPDEFNAM:  //data type definition name
            case DRDA_CP_TYPDEFOVR:  //data type definition override
            case DRDA_CP_SECTKNOVR:  //sectkn overrides
            case DRDA_CP_SQLDARD:    //SQLDA reply data
            case DRDA_CP_MONITORRD:  //monitor reply data
            case DRDA_CP_MGRLVLOVR:  //manager level overrides
                i_ret = db2_skip_ddm(p_st_fragment, i_whole_flg);
                break;

            case DRDA_CP_SQLCARD:    //SQLCA reply data
                i_ret = db2_parse_sqlcard(p_st_private, i_whole_flg
                                         , &p_st_resp->i_error_code
                                         , p_st_resp->arr_sqlstate, NULL);
                break;

            case DRDA_CP_ABNUOWRM:   //Abnormal End Unit of Work Condition
                i_ret = db2_parse_abnuowrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_AGNPRMRM:   //Permanent Agent Error
                i_ret = db2_parse_agnprmrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDATHRM:   //Not Authorized to Command
                i_ret = db2_parse_cmdathrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDCHKRM:   //Command Check
                i_ret = db2_parse_cmdchkrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDNSPRM:   //Command Not Supported
                i_ret = db2_parse_cmdnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_DTAMCHRM:   //Data Descriptor Mismatch
                i_ret = db2_parse_dtamchrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_OBJNSPRM:   //Object Not Supported
                i_ret = db2_parse_objnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PKGBPARM:   //RDB Package Binding Process Active
                i_ret = db2_parse_pkgbparm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PRCCNVRM:   //Conversational Protocol Error
                i_ret = db2_parse_prccnvrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PRMNSPRM:   //Parameter Not Supported
                i_ret = db2_parse_prmnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_RDBNACRM:   //RDB Not Accessed
                i_ret = db2_parse_rdbnacrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_RSCLMTRM:   //Resource Limits Reached
                i_ret = db2_parse_rsclmtrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_SQLERRRM:   //SQL Error Condition
                i_ret = db2_parse_sqlerrrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_SYNTAXRM:   //Data Stream Syntax Error
                i_ret = db2_parse_syntaxrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_TRGNSPRM:   //Target Not Supported
                i_ret = db2_parse_trgnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_VALNSPRM:   //Parameter Value Not Supported
                i_ret = db2_parse_valnsprm(p_st_private, i_whole_flg);
                break;

            default:
                frdbg("PRPSQLSTT response: Unknow DDM!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 需要更多的数据或者解析出错 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("PRPSQLSTT response: need more data or parse failed!\n");
            return i_ret;
        }

        /* 设置position */
        p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
        /* 当前object或者message解析完成 */
        p_st_fragment->i_req_resp_cp = DRDA_CP_NULL;
        /* 下一个可能存在的DDM object属于下一个command的response */
        if (p_st_fragment->i_correlator_flg == DB2_FALSE)
        {
            i_ret = __db2_end_resp_cmd(p_st_private, p_st_cmd_cp);
            return i_ret;
        }
    }

    return APM_L7_ANALYZE_TODO;
}

/*******************************************************************************
*  FUNC     :  解析OPNQRY对应的响应
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(保存Frreport_data)
*           :  p_st_private(DB2是有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_parse_opnqry_resp(Conntrack *p_st_conn
                                  , Frhash_header *p_st_hash_report
                                  , L7session_db2_private *p_st_private
                                  , int i_whole_flg
                                  , Db2_req_cmd *p_st_cmd_cp)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_ddm_cp = 0;
    L7_resp_db2 *p_st_resp = p_st_private->p_st_resp;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    while (bytebuff_remaining(p_st_data) > 0)
    {
        /* 取得当前DDM的code point */
        i_ret = db2_get_ddm_cp(p_st_fragment, i_whole_flg, &i_ddm_cp
                              , &p_st_resp->ui_ddm_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("OPNQRY response: need more data or parse failed!\n");
            return i_ret;
        }

        switch(i_ddm_cp)
        {
            /* 跳过该object */
            case DRDA_CP_EXTDTA:    //externalized FD:OCA data
            case DRDA_CP_MGRLVLOVR: //manager level overrides
            case DRDA_CP_MONITORRD: //monitor reply data
            case DRDA_CP_SECTKNOVR: //sectkn overrides
            case DRDA_CP_TYPDEFNAM: //data type definition name
            case DRDA_CP_TYPDEFOVR: //data type definition override
            case DRDA_CP_RDBUPDRM:  //RDB update
            case DRDA_CP_OPNQRYRM:  //open query completed
            case DRDA_CP_SQLDARD:   //SQLDA Reply Data
                i_ret = db2_skip_ddm(p_st_fragment, i_whole_flg);
                break;

            case DRDA_CP_SQLCARD:   //SQLCA reply data
                i_ret = db2_parse_sqlcard(p_st_private, i_whole_flg
                                         , &p_st_resp->i_error_code
                                         , p_st_resp->arr_sqlstate, NULL);
                break;

            case DRDA_CP_QRYDSC:    //query answer set description
                i_ret = db2_get_fdodsc(p_st_data, i_whole_flg
                                      , p_st_fragment->ui_left_ddm_len
                                      , &p_st_cmd_cp->p_st_statement->st_metadata_column
                                      , &p_st_fragment->ui_left_ddm_len);
                break;

            case DRDA_CP_QRYDTA:    //query answer set data
                if (p_st_fragment->i_exter_flg == DB2_TRUE)
                {
                    i_ret = db2_get_exter_fetch_rows(p_st_private
                                                    , &p_st_cmd_cp->p_st_statement->st_metadata_column
                                                    , &p_st_resp->ul_rows);
                }
                else
                {
                    i_ret = db2_get_fetch_rows(p_st_private, i_whole_flg
                                              , &p_st_cmd_cp->p_st_statement->st_metadata_column
                                              , &p_st_resp->ul_rows
                                              , p_st_cmd_cp);
                }
                break;

            case DRDA_CP_ENDQRYRM: //end of query condition
                i_ret = db2_parse_endqryrm(p_st_private, i_whole_flg);
                if (i_ret != APM_L7_ANALYZE_SUCC)
                {
                    frdbg("OPNQRY response: need more data or parse failed!\n");
                    return i_ret;
                }
                /* ENDQRYRM意味着query结束,需要将request上报 */
                __db2_report_resp_req(p_st_conn, p_st_hash_report
                                     , p_st_cmd_cp, p_st_private->p_st_sess);
                break;

            case DRDA_CP_ABNUOWRM:   //Abnormal End Unit of Work Con
                i_ret = db2_parse_abnuowrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_AGNPRMRM:   //Permanent Agent Error
                i_ret = db2_parse_agnprmrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDATHRM:   //Not Authorized to Command
                i_ret = db2_parse_cmdathrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDCHKRM:   //Command Check
                i_ret = db2_parse_cmdchkrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDNSPRM:   //Command Not Supported
                i_ret = db2_parse_cmdnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_DSCINVRM:   //Invalid Description
                i_ret = db2_parse_dscinvrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_DTAMCHRM:   //Data Descriptor Mismatch
                i_ret = db2_parse_dtamchrm(p_st_private, i_whole_flg);
                break;

            //根据DB2文档该正常reply message不会出现在OPNQRY响应中
            case DRDA_CP_ENDDTARM:   //End of Data
                i_ret = db2_parse_enddtarm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_ENDUOWRM:   //End Unit of Work Condition
                i_ret = db2_parse_enduowrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_OBJNSPRM:   //Object Not Supported
                i_ret = db2_parse_objnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_OPNQFLRM:   //Open Query Failure
                i_ret = db2_parse_opnqflrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PKGBPARM:   //RDB Package Binding Process A
                i_ret = db2_parse_pkgbparm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PRCCNVRM:   //Conversational Protocol Error
                i_ret = db2_parse_prccnvrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PRMNSPRM:   //Parameter Not Supported
                i_ret = db2_parse_prmnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_QRYPOPRM:   //Query Previously Opened
                i_ret = db2_parse_qrypoprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_RDBNACRM:   //RDB Not Accessed
                i_ret = db2_parse_rdbnacrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_RSCLMTRM:   //Resource Limits Reached
                i_ret = db2_parse_rsclmtrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_SYNTAXRM:   //Data Stream Syntax Error
                i_ret = db2_parse_syntaxrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_TRGNSPRM:   //Target Not Supported
                i_ret = db2_parse_trgnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_VALNSPRM:   //Parameter Value Not Supported
                i_ret = db2_parse_valnsprm(p_st_private, i_whole_flg);
                break;

            default:
                frdbg("OPNQRY response: Unknow DDM!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 需要更多的数据或者解析出错 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("OPNQRY response: need more data or parse failed[%d]!\n", i_ddm_cp);
            return i_ret;
        }

        /* 设置position */
        p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
        /* 当前object或者message解析完成 */
        p_st_fragment->i_req_resp_cp = DRDA_CP_NULL;
        /* 下一个可能存在的DDM object属于下一个command的response */
        if (p_st_fragment->i_correlator_flg == DB2_FALSE
            || (p_st_fragment->i_exter_flg == DB2_TRUE
                && p_st_fragment->i_exter_whole_flg == DB2_TRUE))

        {
            i_ret = __db2_end_resp_cmd(p_st_private, p_st_cmd_cp);
            return i_ret;
        }
    }

    return APM_L7_ANALYZE_TODO;
}


/*******************************************************************************
*  FUNC     :  解析CNTQRY对应的响应
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(保存Frreport_data)
*           :  p_st_private(DB2是有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_parse_cntqry_resp(Conntrack *p_st_conn
                                  , Frhash_header *p_st_hash_report
                                  , L7session_db2_private *p_st_private
                                  , int i_whole_flg
                                  , Db2_req_cmd *p_st_cmd_cp)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_ddm_cp = 0;
    L7_resp_db2 *p_st_resp = p_st_private->p_st_resp;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    while (bytebuff_remaining(p_st_data) > 0)
    {
        /* 取得当前DDM的code point */
        i_ret = db2_get_ddm_cp(p_st_fragment, i_whole_flg, &i_ddm_cp
                              , &p_st_resp->ui_ddm_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("CNTQRY response: need more data or parse failed!\n");
            return i_ret;
        }

        switch(i_ddm_cp)
        {
            /* 跳过该object */
            case DRDA_CP_EXTDTA:    //externalized FD:OCA data
            case DRDA_CP_MGRLVLOVR: //manager level overrides
            case DRDA_CP_MONITORRD: //monitor reply data
            case DRDA_CP_SECTKNOVR: //sectkn overrides
            case DRDA_CP_TYPDEFNAM: //data type definition name
            case DRDA_CP_TYPDEFOVR: //data type definition override
            case DRDA_CP_RDBUPDRM: //RDB update
                i_ret = db2_skip_ddm(p_st_fragment, i_whole_flg);
                break;

            case DRDA_CP_SQLCARD:   //SQLCA reply data
                i_ret = db2_parse_sqlcard(p_st_private, i_whole_flg
                                         , &p_st_resp->i_error_code
                                         , p_st_resp->arr_sqlstate, NULL);
                break;

            case DRDA_CP_QRYDTA:    //query answer set data
                if (p_st_fragment->i_exter_flg == DB2_TRUE)
                {
                    i_ret = db2_get_exter_fetch_rows(p_st_private
                                                    , &p_st_cmd_cp->p_st_statement->st_metadata_column
                                                    , &p_st_resp->ul_rows);
                }
                else
                {
                    i_ret = db2_get_fetch_rows(p_st_private, i_whole_flg
                                              , &p_st_cmd_cp->p_st_statement->st_metadata_column
                                              , &p_st_resp->ul_rows
                                              , p_st_cmd_cp);
                }
                break;

            case DRDA_CP_ENDQRYRM: //end of query condition
                i_ret = db2_parse_endqryrm(p_st_private, i_whole_flg);
                if (i_ret != APM_L7_ANALYZE_SUCC)
                {
                    frdbg("CNTQRY response: need more data or parse failed!\n");
                    return i_ret;
                }
                /* ENDQRYRM意味着query结束,需要将request上报 */
                __db2_report_resp_req(p_st_conn, p_st_hash_report
                                      , p_st_cmd_cp, p_st_private->p_st_sess);
                break;

            case DRDA_CP_ABNUOWRM:   //Abnormal End Unit of Work Con
                i_ret = db2_parse_abnuowrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_AGNPRMRM:   //Permanent Agent Error
                i_ret = db2_parse_agnprmrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDATHRM:   //Not Authorized to Command
                i_ret = db2_parse_cmdathrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDCHKRM:   //Command Check
                i_ret = db2_parse_cmdchkrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDNSPRM:   //Command Not Supported
                i_ret = db2_parse_cmdnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_ENDDTARM:   //End of Data
                i_ret = db2_parse_enddtarm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_ENDUOWRM:   //End Unit of Work Condition
                i_ret = db2_parse_enduowrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PKGBPARM:   //RDB Package Binding Process A
                i_ret = db2_parse_pkgbparm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PRCCNVRM:   //Conversational Protocol Error
                i_ret = db2_parse_prccnvrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PRMNSPRM:   //Parameter Not Supported
                i_ret = db2_parse_prmnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_QRYPOPRM:   //Query Previously Opened
                i_ret = db2_parse_qrypoprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_RDBNACRM:   //RDB Not Accessed
                i_ret = db2_parse_rdbnacrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_RSCLMTRM:   //Resource Limits Reached
                i_ret = db2_parse_rsclmtrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_SYNTAXRM:   //Data Stream Syntax Error
                i_ret = db2_parse_syntaxrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_TRGNSPRM:   //Target Not Supported
                i_ret = db2_parse_trgnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_VALNSPRM:   //Parameter Value Not Supported
                i_ret = db2_parse_valnsprm(p_st_private, i_whole_flg);
                break;

            default:
                frdbg("CNTQRY response: Unknow DDM!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 需要更多的数据或者解析出错 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("CNTQRY response: need more data or parse failed!\n");
            return i_ret;
        }

        /* 设置position */
        p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
        /* 当前object或者message解析完成 */
        p_st_fragment->i_req_resp_cp = DRDA_CP_NULL;
        /* 下一个可能存在的DDM object属于下一个command的response */
        if (p_st_fragment->i_correlator_flg == DB2_FALSE
            || (p_st_fragment->i_exter_flg == DB2_TRUE
                && p_st_fragment->i_exter_whole_flg == DB2_TRUE))
        {
            i_ret = __db2_end_resp_cmd(p_st_private, p_st_cmd_cp);
            return i_ret;
        }
    }

    return APM_L7_ANALYZE_TODO;
}

/*******************************************************************************
*  FUNC     :  解析CLSQRY对应的响应
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(保存Frreport_data)
*           :  p_st_private(DB2是有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_parse_clsqry_resp(Conntrack *p_st_conn
                                  , Frhash_header *p_st_hash_report
                                  , L7session_db2_private *p_st_private
                                  , int i_whole_flg
                                  , Db2_req_cmd *p_st_cmd_cp)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_ddm_cp = 0;
    L7_resp_db2 *p_st_resp = p_st_private->p_st_resp;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    while (bytebuff_remaining(p_st_data) > 0)
    {
        /* 取得当前DDM的code point */
        i_ret = db2_get_ddm_cp(p_st_fragment, i_whole_flg, &i_ddm_cp
                              , &p_st_private->p_st_resp->ui_ddm_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("CLSQRY response: need more data or parse failed!\n");
            return i_ret;
        }

        switch(i_ddm_cp)
        {
            /* 跳过该object */
            case DRDA_CP_TYPDEFNAM: //data type definition name
            case DRDA_CP_TYPDEFOVR: //data type definition override
            case DRDA_CP_MONITORRD: //monitor reply data
            case DRDA_CP_MGRLVLOVR: //manager level overrides
                i_ret = db2_skip_ddm(p_st_fragment, i_whole_flg);
                break;

            case DRDA_CP_SQLCARD:   //SQLCA reply data
                i_ret = db2_parse_sqlcard(p_st_private, i_whole_flg
                                         , &p_st_resp->i_error_code
                                         , p_st_resp->arr_sqlstate, NULL);
                break;

            case DRDA_CP_ABNUOWRM:  //Abnormal End Unit of Work Condition
                i_ret = db2_parse_abnuowrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_AGNPRMRM:  //Permanent Agent Error
                i_ret = db2_parse_agnprmrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDATHRM:  //Not Authorized to Command
                i_ret = db2_parse_cmdathrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDCHKRM:  //Command Check
                i_ret = db2_parse_cmdchkrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDNSPRM:  //Command Not Supported
                i_ret = db2_parse_cmdnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PKGBPARM:  //RDB Package Binding Process Active
                i_ret = db2_parse_pkgbparm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PRCCNVRM:  //Conversational Protocol Error
                i_ret = db2_parse_prccnvrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PRMNSPRM:  //Parameter Not Supported
                i_ret = db2_parse_prmnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_QRYNOPRM:  //Query Not Open
                i_ret = db2_parse_qrynoprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_RDBNACRM:  //RDB Not Accessed
                i_ret = db2_parse_rdbnacrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_RSCLMTRM:  //Resource Limits Reached
                i_ret = db2_parse_rsclmtrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_SYNTAXRM:  //Data Stream Syntax Error
                i_ret = db2_parse_syntaxrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_TRGNSPRM:  //Target Not Supported
                i_ret = db2_parse_trgnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_VALNSPRM:  //Parameter Value Not Supported
                i_ret = db2_parse_valnsprm(p_st_private, i_whole_flg);
                break;

            default:
                frdbg("CLSQRY response: Unknow DDM!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 需要更多的数据或者解析出错 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("CLSQRY response: need more data or parse failed!\n");
            return i_ret;
        }

        /* 设置position */
        p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
        /* 当前object或者message解析完成 */
        p_st_fragment->i_req_resp_cp = DRDA_CP_NULL;
        /* 下一个可能存在的DDM object属于下一个command的response */
        if (p_st_fragment->i_correlator_flg == DB2_FALSE)
        {
            i_ret = __db2_end_resp_cmd(p_st_private, p_st_cmd_cp);
            return i_ret;
        }
    }

    return APM_L7_ANALYZE_TODO;
}

/*******************************************************************************
*  FUNC     :  解析RDBCMM对应的响应
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(保存Frreport_data)
*           :  p_st_private(DB2是有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_parse_rdbcmm_resp(Conntrack *p_st_conn
                                  , Frhash_header *p_st_hash_report
                                  , L7session_db2_private *p_st_private
                                  , int i_whole_flg
                                  , Db2_req_cmd *p_st_cmd_cp)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_ddm_cp = 0;
    L7_resp_db2 *p_st_resp = p_st_private->p_st_resp;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    while (bytebuff_remaining(p_st_data) > 0)
    {
        /* 取得当前DDM的code point */
        i_ret = db2_get_ddm_cp(p_st_fragment, i_whole_flg, &i_ddm_cp
                              , &p_st_private->p_st_resp->ui_ddm_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("RDBCMM response: need more data or parse failed!\n");
            return i_ret;
        }

        switch(i_ddm_cp)
        {
            /* 跳过该object */
            case DRDA_CP_MGRLVLOVR: //manager level overrides
            case DRDA_CP_SQLSTT:    //SQL statements
            case DRDA_CP_TYPDEFNAM: //data type definition name
            case DRDA_CP_TYPDEFOVR: //data type definition override
            case DRDA_CP_MONITORRD: //协议中没有，数据包中有
                i_ret = db2_skip_ddm(p_st_fragment, i_whole_flg);
                break;

            case DRDA_CP_SQLCARD:
                i_ret = db2_parse_sqlcard(p_st_private, i_whole_flg
                                         , &p_st_resp->i_error_code
                                         , p_st_resp->arr_sqlstate, NULL);
                break;

            case DRDA_CP_CMDVLTRM:  //Command Violation
                i_ret = db2_parse_cmdvltrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_ENDUOWRM:  //End Unit of Work Condition
                i_ret = db2_parse_enduowrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_ABNUOWRM:   //Abnormal End Unit of Work Condition
                i_ret = db2_parse_abnuowrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_AGNPRMRM:   //Permanent Agent Error
                i_ret = db2_parse_agnprmrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDATHRM:   //Not Authorized to Command
                i_ret = db2_parse_cmdathrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDCHKRM:   //Command Check
                i_ret = db2_parse_cmdchkrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDNSPRM:   //Command Not Supported
                i_ret = db2_parse_cmdnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PRCCNVRM:   //Conversational Protocol Error
                i_ret = db2_parse_prccnvrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PRMNSPRM:   //Parameter Not Supported
                i_ret = db2_parse_prmnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_RDBNACRM:   //RDB Not Accessed
                i_ret = db2_parse_rdbnacrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_RSCLMTRM:   //Resource Limits Reached
                i_ret = db2_parse_rsclmtrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_SYNTAXRM:   //Data Stream Syntax Error
                i_ret = db2_parse_syntaxrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_TRGNSPRM:   //Target Not Supported
                i_ret = db2_parse_trgnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_VALNSPRM:   //Parameter Value Not Supported
                i_ret = db2_parse_valnsprm(p_st_private, i_whole_flg);
                break;

            default:
                frdbg("RDBCMM response: Unknow DDM!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 需要更多的数据或者解析出错 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("RDBCMM response: need more data or parse failed!\n");
            return i_ret;
        }

        /* 设置position */
        p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
        /* 当前object或者message解析完成 */
        p_st_fragment->i_req_resp_cp = DRDA_CP_NULL;
        /* 下一个可能存在的DDM object属于下一个command的response */
        if (p_st_fragment->i_correlator_flg == DB2_FALSE)
        {
            i_ret = __db2_end_resp_cmd(p_st_private, p_st_cmd_cp);
            return i_ret;
        }
    }

    return APM_L7_ANALYZE_TODO;
}

/*******************************************************************************
*  FUNC     :  解析RDBRLLBCK对应的响应
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(保存Frreport_data)
*           :  p_st_private(DB2是有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_parse_rdbrllbck_resp(Conntrack *p_st_conn
                                     , Frhash_header *p_st_hash_report
                                     , L7session_db2_private *p_st_private
                                     , int i_whole_flg
                                     , Db2_req_cmd *p_st_cmd_cp)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_ddm_cp = 0;
    L7_resp_db2 *p_st_resp = p_st_private->p_st_resp;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    while (bytebuff_remaining(p_st_data) > 0)
    {
        /* 取得当前DDM的code point */
        i_ret = db2_get_ddm_cp(p_st_fragment, i_whole_flg, &i_ddm_cp
                              , &p_st_private->p_st_resp->ui_ddm_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("RDBRLLBCK response: need more data or parse failed!\n");
            return i_ret;
        }

        switch(i_ddm_cp)
        {
            /* 跳过该object */
            case DRDA_CP_MGRLVLOVR: //manager level overrides
            case DRDA_CP_SQLSTT:    //SQL statements
            case DRDA_CP_TYPDEFNAM: //data type definition name
            case DRDA_CP_TYPDEFOVR: //data type definition override
            case DRDA_CP_MONITORRD: //协议中没有，数据包中可能有
                i_ret = db2_skip_ddm(p_st_fragment, i_whole_flg);
                break;

            case DRDA_CP_SQLCARD:
                i_ret = db2_parse_sqlcard(p_st_private, i_whole_flg
                                         , &p_st_resp->i_error_code
                                         , p_st_resp->arr_sqlstate, NULL);
                break;

            case DRDA_CP_CMDVLTRM:  //Command Violation
                i_ret = db2_parse_cmdvltrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_ENDUOWRM:  //End Unit of Work Condition
                i_ret = db2_parse_enduowrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_AGNPRMRM:   //Permanent Agent Error
                i_ret = db2_parse_agnprmrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDATHRM:   //Not Authorized to Command
                i_ret = db2_parse_cmdathrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDCHKRM:   //Command Check
                i_ret = db2_parse_cmdchkrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDNSPRM:   //Command Not Supported
                i_ret = db2_parse_cmdnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PRCCNVRM:   //Conversational Protocol Error
                i_ret = db2_parse_prccnvrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PRMNSPRM:   //Parameter Not Supported
                i_ret = db2_parse_prmnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_RDBNACRM:   //RDB Not Accessed
                i_ret = db2_parse_rdbnacrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_RSCLMTRM:   //Resource Limits Reached
                i_ret = db2_parse_rsclmtrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_SYNTAXRM:   //Data Stream Syntax Error
                i_ret = db2_parse_syntaxrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_TRGNSPRM:   //Target Not Supported
                i_ret = db2_parse_trgnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_VALNSPRM:   //Parameter Value Not Supported
                i_ret = db2_parse_valnsprm(p_st_private, i_whole_flg);
                break;

            default:
                frdbg("RDBRLLBCK response: Unknow DDM!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 需要更多的数据或者解析出错 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("RDBRLLBCK response: need more data or parse failed!\n");
            return i_ret;
        }

        /* 设置position */
        p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
        /* 当前object或者message解析完成 */
        p_st_fragment->i_req_resp_cp = DRDA_CP_NULL;
        /* 下一个可能存在的DDM object属于下一个command的response */
        if (p_st_fragment->i_correlator_flg == DB2_FALSE)
        {
            i_ret = __db2_end_resp_cmd(p_st_private, p_st_cmd_cp);
            return i_ret;
        }
    }

    return APM_L7_ANALYZE_TODO;
}

/*******************************************************************************
*  FUNC     :  解析EXCSQLIMM对应的响应
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(保存Frreport_data)
*           :  p_st_private(DB2是有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_parse_excsqlimm_resp(Conntrack *p_st_conn
                                     , Frhash_header *p_st_hash_report
                                     , L7session_db2_private *p_st_private
                                     , int i_whole_flg
                                     , Db2_req_cmd *p_st_cmd_cp)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_ddm_cp = 0;
    L7_resp_db2 *p_st_resp = p_st_private->p_st_resp;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    while (bytebuff_remaining(p_st_data) > 0)
    {
        /* 取得当前DDM的code point */
        i_ret = db2_get_ddm_cp(p_st_fragment, i_whole_flg, &i_ddm_cp
                              , &p_st_private->p_st_resp->ui_ddm_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("EXCSQLIMM response: need more data or parse failed!\n");
            return i_ret;
        }

        switch(i_ddm_cp)
        {
            /* 跳过该object */
            case DRDA_CP_MGRLVLOVR: //manager level overrides
            case DRDA_CP_SQLSTT:    //SQL statements
            case DRDA_CP_TYPDEFNAM: //data type definition name
            case DRDA_CP_TYPDEFOVR: //data type definition override
            case DRDA_CP_RDBUPDRM:  //RDB update
                i_ret = db2_skip_ddm(p_st_fragment, i_whole_flg);
                break;

            case DRDA_CP_SQLCARD:
                i_ret = db2_parse_sqlcard(p_st_private, i_whole_flg
                                         , &p_st_resp->i_error_code
                                         , p_st_resp->arr_sqlstate
                                         , &p_st_resp->ul_effect_rows);
                break;

            case DRDA_CP_CMMRQSRM:  //commitment request
                i_ret = db2_parse_cmmrqsrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_ENDUOWRM:  //End Unit of Work Condition
                i_ret = db2_parse_enduowrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_ABNUOWRM:  //Abnormal End Unit of Work Condition
                i_ret = db2_parse_abnuowrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_AGNPRMRM:   //Permanent Agent Error
                i_ret = db2_parse_agnprmrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDATHRM:   //Not Authorized to Command
                i_ret = db2_parse_cmdathrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDCHKRM:   //Command Check
                i_ret = db2_parse_cmdchkrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDNSPRM:   //Command Not Supported
                i_ret = db2_parse_cmdnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_DTAMCHRM:   //Data Descriptor Mismatch
                i_ret = db2_parse_dtamchrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_OBJNSPRM:   //Object Not Supported
                i_ret = db2_parse_objnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PKGBPARM:   //RDB Package Binding Process Active
                i_ret = db2_parse_pkgbparm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PRCCNVRM:   //Conversational Protocol Error
                i_ret = db2_parse_prccnvrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PRMNSPRM:   //Parameter Not Supported
                i_ret = db2_parse_prmnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_RDBNACRM:   //RDB Not Accessed
                i_ret = db2_parse_rdbnacrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_RSCLMTRM:   //Resource Limits Reached
                i_ret = db2_parse_rsclmtrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_SQLERRRM:   //SQL Error Condition
                i_ret = db2_parse_sqlerrrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_SYNTAXRM:   //Data Stream Syntax Error
                i_ret = db2_parse_syntaxrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_TRGNSPRM:   //Target Not Supported
                i_ret = db2_parse_trgnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_VALNSPRM:   //Parameter Value Not Supported
                i_ret = db2_parse_valnsprm(p_st_private, i_whole_flg);
                break;

            default:
                frdbg("EXCSQLIMM response: Unknow DDM!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 需要更多的数据或者解析出错 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("RDBRLLBCK response: need more data or parse failed!\n");
            return i_ret;
        }

        /* 设置position */
        p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
        /* 当前object或者message解析完成 */
        p_st_fragment->i_req_resp_cp = DRDA_CP_NULL;
        /* 下一个可能存在的DDM object属于下一个command的response */
        if (p_st_fragment->i_correlator_flg == DB2_FALSE)
        {
            i_ret = __db2_end_resp_cmd(p_st_private, p_st_cmd_cp);
            return i_ret;
        }
    }

    return APM_L7_ANALYZE_TODO;
}

/*******************************************************************************
*  FUNC     :  解析DSCSQLSTT对应的响应
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(保存Frreport_data)
*           :  p_st_private(DB2是有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_parse_dscsqlstt_resp(Conntrack *p_st_conn
                                     , Frhash_header *p_st_hash_report
                                     , L7session_db2_private *p_st_private
                                     , int i_whole_flg
                                     , Db2_req_cmd *p_st_cmd_cp)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_ddm_cp = 0;
    L7_resp_db2 *p_st_resp = p_st_private->p_st_resp;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    while (bytebuff_remaining(p_st_data) > 0)
    {
        /* 取得当前DDM的code point */
        i_ret = db2_get_ddm_cp(p_st_fragment, i_whole_flg, &i_ddm_cp
                              , &p_st_private->p_st_resp->ui_ddm_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("PRPSQLSTT response: need more data or parse failed!\n");
            return i_ret;
        }

        switch(i_ddm_cp)
        {
            /* 跳过该object */
            case DRDA_CP_TYPDEFNAM:  //data type definition name
            case DRDA_CP_TYPDEFOVR:  //data type definition override
            case DRDA_CP_SECTKNOVR:  //sectkn overrides
            case DRDA_CP_SQLDARD:    //SQLDA reply data
            case DRDA_CP_MONITORRD:  //monitor reply data
            case DRDA_CP_MGRLVLOVR:  //manager level overrides
                i_ret = db2_skip_ddm(p_st_fragment, i_whole_flg);
                break;

            case DRDA_CP_SQLCARD:    //SQLCA reply data
                i_ret = db2_parse_sqlcard(p_st_private, i_whole_flg
                                         , &p_st_resp->i_error_code
                                         , p_st_resp->arr_sqlstate, NULL);
                break;

            case DRDA_CP_ABNUOWRM:   //Abnormal End Unit of Work Condition
                i_ret = db2_parse_abnuowrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_AGNPRMRM:   //Permanent Agent Error
                i_ret = db2_parse_agnprmrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDATHRM:   //Not Authorized to Command
                i_ret = db2_parse_cmdathrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDCHKRM:   //Command Check
                i_ret = db2_parse_cmdchkrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDNSPRM:   //Command Not Supported
                i_ret = db2_parse_cmdnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PKGBPARM:   //RDB Package Binding Process Active
                i_ret = db2_parse_pkgbparm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PRCCNVRM:   //Conversational Protocol Error
                i_ret = db2_parse_prccnvrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PRMNSPRM:   //Parameter Not Supported
                i_ret = db2_parse_prmnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_RDBNACRM:   //RDB Not Accessed
                i_ret = db2_parse_rdbnacrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_RSCLMTRM:   //Resource Limits Reached
                i_ret = db2_parse_rsclmtrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_SQLERRRM:   //SQL Error Condition
                i_ret = db2_parse_sqlerrrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_SYNTAXRM:   //Data Stream Syntax Error
                i_ret = db2_parse_syntaxrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_TRGNSPRM:   //Target Not Supported
                i_ret = db2_parse_trgnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_VALNSPRM:   //Parameter Value Not Supported
                i_ret = db2_parse_valnsprm(p_st_private, i_whole_flg);
                break;

            default:
                frdbg("DSCSQLSTT response: Unknow DDM!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 需要更多的数据或者解析出错 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("DSCSQLSTT response: need more data or parse failed!\n");
            return i_ret;
        }

        /* 设置position */
        p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
        /* 当前object或者message解析完成 */
        p_st_fragment->i_req_resp_cp = DRDA_CP_NULL;
        /* 下一个可能存在的DDM object属于下一个command的response */
        if (p_st_fragment->i_correlator_flg == DB2_FALSE)
        {
            i_ret = __db2_end_resp_cmd(p_st_private, p_st_cmd_cp);
            return i_ret;
        }
    }

    return APM_L7_ANALYZE_TODO;
}

/*******************************************************************************
*  FUNC     :  解析EXCSQLSTT对应的响应
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(保存Frreport_data)
*           :  p_st_private(DB2是有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_parse_excsqlstt_resp(Conntrack *p_st_conn
                                     , Frhash_header *p_st_hash_report
                                     , L7session_db2_private *p_st_private
                                     , int i_whole_flg
                                     , Db2_req_cmd *p_st_cmd_cp)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_ddm_cp = 0;
    L7_resp_db2 *p_st_resp = p_st_private->p_st_resp;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    while (bytebuff_remaining(p_st_data) > 0)
    {
        /* 取得当前DDM的code point */
        i_ret = db2_get_ddm_cp(p_st_fragment, i_whole_flg, &i_ddm_cp
                              , &p_st_private->p_st_resp->ui_ddm_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("EXCSQLSTT response: need more data or parse failed!\n");
            return i_ret;
        }

        switch(i_ddm_cp)
        {
            /* 跳过以下object */
            case DRDA_CP_EXTDTA:     //externalized FD:OCA data
            case DRDA_CP_MONITORRD:  //monitor reply data
            case DRDA_CP_MGRLVLOVR:  //manager level overrides
            case DRDA_CP_SECTKNOVR:  //sectkn overrides
            case DRDA_CP_SQLCINRD:   //SQL result set column information reply data
            case DRDA_CP_SQLDTARD:   //SQL data reply data
            case DRDA_CP_SQLRSLRD:   //SQL result set reply data
            case DRDA_CP_TYPDEFNAM:  //data type definition name
            case DRDA_CP_TYPDEFOVR:  //data type definition override
            case DRDA_CP_RSLSETRM:   //RDB Result Set Reply Message
            case DRDA_CP_RDBUPDRM:   //RDBUPDRM
                i_ret = db2_skip_ddm(p_st_fragment, i_whole_flg);
                break;

            case DRDA_CP_SQLCARD:    //SQLCA reply data
                i_ret = db2_parse_sqlcard(p_st_private, i_whole_flg
                                         , &p_st_resp->i_error_code
                                         , p_st_resp->arr_sqlstate
                                         , &p_st_resp->ul_effect_rows);
                break;

            case DRDA_CP_QRYDSC:    //query answer set description
                i_ret = db2_get_fdodsc(p_st_data, i_whole_flg
                                      , p_st_fragment->ui_left_ddm_len
                                      , &p_st_cmd_cp->p_st_statement->st_metadata_column
                                      , &p_st_fragment->ui_left_ddm_len);
                break;

            case DRDA_CP_QRYDTA:    //query answer set data
                if (p_st_fragment->i_exter_flg == DB2_TRUE)
                {
                    i_ret = db2_get_exter_fetch_rows(p_st_private
                                                    , &p_st_cmd_cp->p_st_statement->st_metadata_column
                                                    , &p_st_resp->ul_rows);
                }
                else
                {
                    i_ret = db2_get_fetch_rows(p_st_private, i_whole_flg
                                              , &p_st_cmd_cp->p_st_statement->st_metadata_column
                                              , &p_st_resp->ul_rows
                                              , p_st_cmd_cp);
                }
                break;

            case DRDA_CP_ENDUOWRM:   //End Unit of Work Condition
                i_ret = db2_parse_enduowrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMMRQSRM:   //Commitment Request
                i_ret = db2_parse_cmmrqsrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_ENDQRYRM: //end of query condition
                i_ret = db2_parse_endqryrm(p_st_private, i_whole_flg);
                if (i_ret != APM_L7_ANALYZE_SUCC)
                {
                    frdbg("EXCSQLSTT response: need more data or parse failed!\n");
                    return i_ret;
                }
                __db2_report_resp_req(p_st_conn, p_st_hash_report
                                     , p_st_cmd_cp, p_st_private->p_st_sess);
                break;

            case DRDA_CP_OPNQRYRM:  //Open Query Complete
                //todo 设置为fetch rows
                i_ret = db2_skip_ddm(p_st_fragment, i_whole_flg);
                break;

            case DRDA_CP_ABNUOWRM:   //Abnormal End Unit of Work Condition
                i_ret = db2_parse_abnuowrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_AGNPRMRM:   //Permanent Agent Error
                i_ret = db2_parse_agnprmrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDATHRM:   //Not Authorized to Command
                i_ret = db2_parse_cmdathrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDCHKRM:   //Command Check
                i_ret = db2_parse_cmdchkrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDNSPRM:   //Command Not Supported
                i_ret = db2_parse_cmdnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PKGBPARM:   //RDB Package Binding Process Active
                i_ret = db2_parse_pkgbparm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PRCCNVRM:   //Conversational Protocol Error
                i_ret = db2_parse_prccnvrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PRMNSPRM:   //Parameter Not Supported
                i_ret = db2_parse_prmnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_RDBNACRM:   //RDB Not Accessed
                i_ret = db2_parse_rdbnacrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_RSCLMTRM:   //Resource Limits Reached
                i_ret = db2_parse_rsclmtrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_SQLERRRM:   //SQL Error Condition
                i_ret = db2_parse_sqlerrrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_SYNTAXRM:   //Data Stream Syntax Error
                i_ret = db2_parse_syntaxrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_TRGNSPRM:   //Target Not Supported
                i_ret = db2_parse_trgnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_VALNSPRM:   //Parameter Value Not Supported
                i_ret = db2_parse_valnsprm(p_st_private, i_whole_flg);
                break;

            default:
                frdbg("DSCSQLSTT response: Unknow DDM!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 需要更多的数据或者解析出错 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("DSCSQLSTT response: need more data or parse failed!\n");
            return i_ret;
        }

        /* 设置position */
        p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
        /* 当前object或者message解析完成 */
        p_st_fragment->i_req_resp_cp = DRDA_CP_NULL;
        /* 下一个可能存在的DDM object属于下一个command的response */
        if (p_st_fragment->i_correlator_flg == DB2_FALSE
            || (p_st_fragment->i_exter_flg == DB2_TRUE
                && p_st_fragment->i_exter_whole_flg == DB2_TRUE))
        {
            i_ret = __db2_end_resp_cmd(p_st_private, p_st_cmd_cp);
            return i_ret;
        }
    }

    return APM_L7_ANALYZE_TODO;
}

/*******************************************************************************
*  FUNC     :  解析SYNCCTL对应的响应
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(保存Frreport_data)
*           :  p_st_private(DB2是有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_parse_syncctl_resp(Conntrack *p_st_conn
                                       , Frhash_header *p_st_hash_report
                                       , L7session_db2_private *p_st_private
                                       , int i_whole_flg
                                       , Db2_req_cmd *p_st_cmd_cp)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_ddm_cp = 0;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    while (bytebuff_remaining(p_st_data) > 0)
    {
        /* 取得当前DDM的code point */
        i_ret = db2_get_ddm_cp(p_st_fragment, i_whole_flg, &i_ddm_cp
                              , &p_st_private->p_st_resp->ui_ddm_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("SYNCCTL response: need more data or parse failed!\n");
            return i_ret;
        }

        switch(i_ddm_cp)
        {
            /* 跳过下列command */
            case DRDA_CP_SYNCCRD:   //Sync Point Control Reply
            case DRDA_CP_SYNCLOG:   //Sync Point Log
            case DRDA_CP_SQLSTT:    //SQL statements
                i_ret = db2_skip_ddm(p_st_fragment, i_whole_flg);
                break;

            case DRDA_CP_AGNPRMRM:  //Permanent Agent Error
                i_ret = db2_parse_agnprmrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CMDCHKRM:  //Command Check
                i_ret = db2_parse_cmdchkrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PRCCNVRM:  //Conversational Protocol Error
                i_ret = db2_parse_prccnvrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PRMNSPRM:  //Parameter Not Supported
                i_ret = db2_parse_prmnsprm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_SYNTAXRM:  //Data Stream Syntax Error
                i_ret = db2_parse_syntaxrm(p_st_private, i_whole_flg);
                break;

            case DRDA_CP_VALNSPRM:  //Parameter Value Not Supported
                i_ret = db2_parse_valnsprm(p_st_private, i_whole_flg);
                break;

            default:
                frdbg("SYNCCTL: Unknow DDM!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 需要更多的数据或者解析出错 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("SYNCCTL response: need more data or parse failed!\n");
            return i_ret;
        }

        /* 设置position */
        p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
        /* 当前object或者message解析完成 */
        p_st_fragment->i_req_resp_cp = DRDA_CP_NULL;
        /* 下一个可能存在的DDM object属于下一个command的response */
        if (p_st_fragment->i_correlator_flg == DB2_FALSE
            || (p_st_fragment->i_exter_flg == DB2_TRUE
                && p_st_fragment->i_exter_whole_flg == DB2_TRUE))
        {
            i_ret = __db2_end_resp_cmd(p_st_private, p_st_cmd_cp);
            return i_ret;
        }
    }

    return APM_L7_ANALYZE_TODO;
}

/*******************************************************************************
*  FUNC     :  解析response
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(保存Frreport_data)
*           :  p_st_private(DB2是有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  参照module.h
*  NOTE     :
*******************************************************************************/
int db2_parse_response(Conntrack *p_st_conn
                      , Frhash_header *p_st_hash_report
                      , L7session_db2_private *p_st_private
                      , int i_whole_flg)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_req_cmd_cp = 0;
    L7_resp_db2 *p_st_resp = NULL;
    Db2_req_cmd *p_st_cmd_cp = NULL;
    Frlist_node *p_st_cmd_node = NULL;
    L7_req_db2 *p_st_req = p_st_private->p_st_req;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* 在此之前没有接受到request信息, 忽略该response信息 */
    if (p_st_req == NULL)
    {
        frdbg("There no request before response!\n");
        /* 如果不是一个完整的response数据包,则需要接收完整个response包后丢弃 */
        if (i_whole_flg == DB2_TRUE)
        {
            db2_init_fragment(p_st_fragment);
            return APM_L7_ANALYZE_SUCC;
        }
        else
        {
            return APM_L7_ANALYZE_TODO;
        }
    }

    /* 创建response信息结构 */
    if (p_st_private->p_st_resp == NULL)
    {
        p_st_private->p_st_resp = db2_create_response();
        if (p_st_private->p_st_resp == NULL)
        {
            frdbg("Create response failed\n");
            return APM_L7_ANALYZE_FAIL;
        }
    }
    p_st_resp = p_st_private->p_st_resp;

    /* 将位置设置到上次解析正确的位置 */
    bytebuff_setPosition(p_st_data, p_st_fragment->u64_parsed_index);
    /* 取得当前解析到对应request的command */
    p_st_cmd_node = frlist_node_idx(&p_st_req->st_command_lst
                                   , p_st_resp->i_parsed_index);
    /* response解析 */
    while (bytebuff_remaining(p_st_data) > 0)
    {
        if (p_st_cmd_node == NULL)
        {
            frdbg("request and response is no matching\n");
            return APM_L7_ANALYZE_FAIL;
        }
        p_st_cmd_cp = (Db2_req_cmd *)FRLIST_GET_NODE_DATA(p_st_cmd_node);
        i_req_cmd_cp = p_st_cmd_cp->i_req_cmd_cp;

        /* 根据request command解析response */
        switch (i_req_cmd_cp)
        {
            case DRDA_CP_EXCSAT:
                //frdbg("__db2_parse_excsat_resp\n");
                i_ret = __db2_parse_excsat_resp(p_st_conn, p_st_hash_report
                                               , p_st_private, i_whole_flg
                                               , p_st_cmd_cp);
                break;

            case DRDA_CP_ACCSEC:
                //frdbg("__db2_parse_accsec_resp\n");
                i_ret = __db2_parse_accsec_resp(p_st_conn, p_st_hash_report
                                               , p_st_private, i_whole_flg
                                               , p_st_cmd_cp);
                break;

            case DRDA_CP_SECCHK:
                //frdbg("__db2_parse_secchk_resp\n");
                i_ret = __db2_parse_secchk_resp(p_st_conn, p_st_hash_report
                                               , p_st_private, i_whole_flg
                                               , p_st_cmd_cp);
                break;

            case DRDA_CP_ACCRDB:
                //frdbg("__db2_parse_accrdb_resp\n");
                i_ret = __db2_parse_accrdb_resp(p_st_conn, p_st_hash_report
                                               , p_st_private, i_whole_flg
                                               , p_st_cmd_cp);
                break;

            case DRDA_CP_EXCSQLSET:
                //frdbg("__db2_parse_excsqlset_resp\n");
                i_ret = __db2_parse_excsqlset_resp(p_st_conn, p_st_hash_report
                                                  , p_st_private, i_whole_flg
                                                  , p_st_cmd_cp);
                break;

            case DRDA_CP_PRPSQLSTT:
                //frdbg("__db2_parse_prpsqlstt_resp\n");
                i_ret = __db2_parse_prpsqlstt_resp(p_st_conn, p_st_hash_report
                                                  , p_st_private, i_whole_flg
                                                  , p_st_cmd_cp);
                break;

            case DRDA_CP_OPNQRY:
                //frdbg("__db2_parse_opnqry_resp\n");
                i_ret = __db2_parse_opnqry_resp(p_st_conn, p_st_hash_report
                                               , p_st_private, i_whole_flg
                                               , p_st_cmd_cp);
                break;

            case DRDA_CP_CNTQRY:
                //frdbg("__db2_parse_cntqry_resp\n");
                i_ret = __db2_parse_cntqry_resp(p_st_conn, p_st_hash_report
                                               , p_st_private, i_whole_flg
                                               , p_st_cmd_cp);
                break;

            case DRDA_CP_CLSQRY:
                //frdbg("__db2_parse_clsqry_resp\n");
                i_ret = __db2_parse_clsqry_resp(p_st_conn, p_st_hash_report
                                               , p_st_private, i_whole_flg
                                               , p_st_cmd_cp);
                break;

            case DRDA_CP_RDBCMM:
                //frdbg("__db2_parse_rdbcmm_resp\n");
                i_ret = __db2_parse_rdbcmm_resp(p_st_conn, p_st_hash_report
                                               , p_st_private, i_whole_flg
                                               , p_st_cmd_cp);
                break;

            case DRDA_CP_EXCSQLIMM:
                //frdbg("__db2_parse_excsqlimm_resp\n");
                i_ret = __db2_parse_excsqlimm_resp(p_st_conn, p_st_hash_report
                                                  , p_st_private, i_whole_flg
                                                  , p_st_cmd_cp);
                break;

            case DRDA_CP_RDBRLLBCK:
                //frdbg("__db2_parse_rdbrllbck_resp\n");
                i_ret = __db2_parse_rdbrllbck_resp(p_st_conn, p_st_hash_report
                                                  , p_st_private, i_whole_flg
                                                  , p_st_cmd_cp);
                break;

            case DRDA_CP_DSCSQLSTT:
                //frdbg("__db2_parse_dscsqlstt_resp\n");
                i_ret = __db2_parse_dscsqlstt_resp(p_st_conn, p_st_hash_report
                                                  , p_st_private, i_whole_flg
                                                  , p_st_cmd_cp);
                break;

            case DRDA_CP_EXCSQLSTT:
                //frdbg("__db2_parse_excsqlstt_resp\n");
                i_ret = __db2_parse_excsqlstt_resp(p_st_conn, p_st_hash_report
                                                  , p_st_private, i_whole_flg
                                                  , p_st_cmd_cp);
                break;

            case DRDA_CP_SYNCCTL:
                //frdbg("__db2_parse_syncctl\n");
                i_ret = __db2_parse_syncctl_resp(p_st_conn, p_st_hash_report
                                                , p_st_private, i_whole_flg
                                                , p_st_cmd_cp);
                break;

            /* 未支持的COMMAND OBJECT */
            case DRDA_CP_BGNBND:
            case DRDA_CP_BNDCPY:
            case DRDA_CP_BNDDPLY:
            case DRDA_CP_BNDSQLSTT:
            case DRDA_CP_DRPPKG:
            case DRDA_CP_ENDBND:
            case DRDA_CP_GETNXTCHK:
            case DRDA_CP_INTRDBRQS:
            case DRDA_CP_REBIND:
            case DRDA_CP_SNDPKT:
            case DRDA_CP_SYNCRSY:
                frdbg("Command type[%d] is not support now!\n", i_req_cmd_cp);
                /* 销毁request和初始化分片包信息*/
                db2_destroy_request(&p_st_private->p_st_req);
                db2_destroy_response(&p_st_private->p_st_resp);
                db2_init_fragment(p_st_private->p_st_fragment);
                return APM_L7_ANALYZE_FAIL;

            default:
                /* 销毁request和初始化分片包信息*/
                db2_destroy_request(&p_st_private->p_st_req);
                db2_destroy_response(&p_st_private->p_st_resp);
                db2_init_fragment(p_st_private->p_st_fragment);
                return APM_L7_ANALYZE_FAIL;
        }

        /* 判断解析结果 */
        if (i_ret == APM_L7_ANALYZE_FAIL)
        {
            /* 销毁request和初始化分片包信息*/
            db2_destroy_request(&p_st_private->p_st_req);
            db2_destroy_response(&p_st_private->p_st_resp);
            db2_init_fragment(p_st_private->p_st_fragment);
            return i_ret;
        }
        else if (i_ret == APM_L7_ANALYZE_TODO)
        {
            return APM_L7_ANALYZE_TODO;
        }
        /* 取得下一个command node */
        p_st_cmd_node = FRLIST_NEXT_NODE(p_st_cmd_node);
        p_st_resp->i_parsed_index += 1;
    }

    /* response解析完了 */
    if (i_whole_flg == DB2_TRUE
       || (p_st_fragment->i_exter_flg == DB2_TRUE
           && p_st_fragment->i_exter_whole_flg == DB2_TRUE))
    {
        /* 上报 */
        i_ret = __db2_report_resp(p_st_conn, p_st_hash_report, p_st_private);
        /* 销毁request和初始化分片包信息*/
        db2_destroy_request(&p_st_private->p_st_req);
        db2_destroy_response(&p_st_private->p_st_resp);
        db2_init_fragment(p_st_private->p_st_fragment);
        return i_ret;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

